
#include <exception>
#include <stdexcept>
#include <string>
#include <sstream>

using std::exception;
using std::string;
using std::ostringstream;

const int MAX_STR_SIZE = 2500;

class VectorException : exception
{
    protected:
        string function_name_;
        int    str_number_;
        char what_string[MAX_STR_SIZE];

    public:
        VectorException(const char* function_name, int str_number);

        const char* AdditionalInfo() const
        {
            ostringstream stream;

            stream << "Function Name: " << function_name_ << "\n"
                   << "String Number: " << str_number_;

            return stream.str().c_str();
        }

        const char* what() const throw()
        {
            ostringstream stream;

            stream << "Exception has been thrown from Vector class, if you're not so stupid.\n" << AdditionalInfo();

            return stream.str().c_str();
        }
        ~VectorException() throw() {}
};

class SizeFaultException : public VectorException
{
    protected:
        int size_;

    public:
        SizeFaultException(const char* function_name, int string_number, int size);

        const char* what() const throw()
        {
            ostringstream stream;

            stream << "It is fault in Vector class with size. You see that it is: " << size_
                   << "\n" << AdditionalInfo();

            return stream.str().c_str();
        }
};

class IndexFaultException : public VectorException
{
    protected:
        int size_;
        int index_;

    public:
        IndexFaultException(const char* function_name, int string_number, int index, int size);

        const char* what() const throw()
        {
            ostringstream stream;

            stream << "It is fault in Vector class with index. You see that it is: " << index_ <<
                      ", when size is " << size_ << ".\n" << AdditionalInfo();

            return stream.str().c_str();
        }
};

VectorException::VectorException(const char* function_name, int string_number):

    function_name_(function_name),
    str_number_(string_number)

    {}

SizeFaultException::SizeFaultException(const char* function_name, int string_number, int size):

    VectorException(function_name, string_number),
    size_(size)

    {}

IndexFaultException::IndexFaultException(const char* function_name, int string_number, int index, int size):

    VectorException(function_name, string_number),
    size_(size),
    index_(index)

    {}
